﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using GraphAPI.Model;

namespace Deisctra
{
    public partial class DeisctraControl : UserControl
    {
        public DeisctraControl()
		{
			InitializeComponent();
		}

		private Graph graph;
        private Graph oldGraph;

        public DeisctraControl(Graph graph)
		{
			InitializeComponent();

			this.graph = graph;
            this.oldGraph = graph;

			graphPanel.Graph = this.graph;

			for (int i = 1; i <= this.graph.EntityCount; i++)
			{
				cmbFrom.Items.Add(i.ToString());
			}
			if (cmbFrom.Items.Count > 0)
				cmbFrom.SelectedIndex = 0;
		}

		private void cmbFrom_SelectedIndexChanged(object sender, EventArgs e)
		{
			graph = new Graph(oldGraph);
			graph.Entitys[cmbFrom.SelectedIndex].ColorMark = Color.Blue;
			graphPanel.Graph = graph;
		}

		private struct VertexInfo
		{
			public bool visited;
			public double mark;
		}

		private void btnAction_Click(object sender, EventArgs e)
		{
			VertexInfo[] vi = new VertexInfo[graph.EntityCount];
			for (int i = 0; i < graph.EntityCount; i++)
			{
				vi[i] = new VertexInfo();
				vi[i].visited = false;
				vi[i].mark = -1;
			}
			
			try
			{
				vi[int.Parse(cmbFrom.SelectedItem.ToString()) - 1].mark = 0;
			}
			catch
			{
				return;
			}

			List<int> notVisitedList = getNotVisted(vi);
			do
			{
				int theLightest = notVisitedList[0];
				double theSmallestMark = vi[theLightest].mark;
				foreach (int cur in notVisitedList)
				{
					if ((vi[cur].mark < theSmallestMark) && (vi[cur].mark != -1))
					{
						theSmallestMark = vi[cur].mark;
						theLightest = cur;
					}
				}
				visitVertex(theLightest, vi);

				notVisitedList = getNotVisted(vi);
			} while (notVisitedList.Count != 0);

			for (int i = 0; i < graph.EntityCount; i++)
				graph.Entitys[i].Weight = vi[i].mark;
			graphPanel.Graph = graph;
		}
		private void visitVertex(int vert, VertexInfo[] vi)
		{
			vi[vert].visited = true;
			List<int> neighbours = new List<int>();
			for (int i = 0; i < graph.EntityCount; i++)
			{
				if (graph.RelationMatrix[vert, i] != false)
					neighbours.Add(i);
			}

			foreach (int cur in neighbours)
			{
				Relation rel = graph.FindRelation(graph.Entitys[vert], graph.Entitys[cur]);
				if (((vi[cur].mark == -1) || (vi[cur].mark > (rel.Weight + vi[vert].mark))) && vi[cur].visited == false)
					vi[cur].mark = rel.Weight + vi[vert].mark;
			}
		}

		private List<int> getNotVisted(VertexInfo[] vi)
		{
			List<int> ret = new List<int>();
			for (int i = 0; i < vi.Length; i++)
			{
				if (vi[i].visited == false && vi[i].mark != -1)
					ret.Add(i);
			}
			return ret;
		}
	}
}
